package 设计模式.创建型.单例模式.一处理资源冲突问题打印日志的程序.通过加对象锁改进一;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 通过这里的锁并不能解决问题，
 * 这是因为，这种锁是一个对象级别的锁，一个对象在不同的线程下同时调用 log() 函数，会被强制要求顺序执行。
 * 但是，不同的对象之间并不共享同一把锁。在不同的线程下，通过不同的对象调用执行 log() 函数，锁并不会起作用，仍然有可能存在写入日志互相覆盖的问题。
 *
 * 这里给 log() 函数加不加对象级别的锁，其实都没有关系。
 * 因为 FileWriter 本身就是线程安全的，它的内部实现中本身就加了对象级别的锁，因此，在外层调用 write() 函数的时候，再加对象级别的锁实际上是多此一举。
 * 因为不同的 Logger 对象不共享 FileWriter 对象，所以，FileWriter 对象级别的锁也解决不了数据写入互相覆盖的问题。
 *
 * 要想解决这个问题也不难，我们只需要把对象级别的锁，换成类级别的锁就可以了。让所有的对象都共享同一把锁。这样就避免了不同对象之间同时调用 log() 函数，而导致的日志覆盖问题。
 */
public class Logger {
    private FileWriter writer;

    public Logger() throws IOException {
        File file = new File("/Users/user/log.txt");
        writer = new FileWriter(file, true);
        //true表示追加写入
    }

    public void log(String message) throws IOException {
        // 对象级别的锁
        synchronized(this) {
            writer.write(message);
        }
    }
}